package cn.com.bluemoon.daps.sync.core.sync.log;

import cn.com.bluemoon.daps.common.constant.DapConstant;
import cn.com.bluemoon.daps.common.enums.SyncStatus;
import cn.com.bluemoon.daps.common.enums.SyncToEnv;
import cn.com.bluemoon.daps.common.exception.DapThrowException;
import cn.com.bluemoon.daps.common.toolkit.BmAssetUtils;
import cn.com.bluemoon.daps.sync.base.BmScript;
import cn.com.bluemoon.daps.sync.core.sync.GlobalConfig;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * 开发同步库表任务表记录表
 * </p>
 *
 * @author admin
 * @since 2021-06-17
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SyncEnvLog {
    public static final String LOG_BASE_PATH = "/data/ptadmin/";
    /**
     * 定义表唯一id eg:发布同步中的任务id dap_sync_prod_env_task.id
     */
    protected String key;
    /**
     * 全局配置
     */
    protected GlobalConfig globalConfig;
    /* 模型id */
    protected String modelId;
    /* 模型表id */
    protected String tableId, tableName;
    /* 任务类型，对应1：开发库同步、2：测试库同步 */
    protected SyncToEnv syncEnv;
    /* ddl语句 */
    protected List<String> syncDdl;
    /* pt工具语句 */
    protected List<String> syncPtsql;
    /* 同步状态，1：同步中 2：已同步 3同步失败 */
    protected SyncStatus syncStatus;
    /* 同步执行人 */
    protected String syncExecBy;
    /* 同步开始时间 */
    protected LocalDateTime syncStartTime;
    /* 同步结束时间 */
    protected LocalDateTime syncEndTime;
    /* 同步日志 */
    protected List<String> syncLog;
    /* 记录该任务所属数据源id */
    protected String dataSourceId;
    /* 记录日志文件路径，用于任务比较长时间处于同步中的，可以通过ssh访问该路径进行获取最新日志 */
    protected String syncLogPath;
    protected String basePath;
    /**
     * 同步环境中是否需要同步到沙箱中模拟
     */
    protected boolean syncSandboxMock = false;
    /**
     * 获取数据建表sql
     */
    protected String tableCreateSql;

    /* 执行脚本的完整语句 */
    protected List<BmScript> syncScript = new ArrayList<>();

    /**
     * @return 初步构建日志实体
     */
    public static SyncEnvLog createLog(GlobalConfig globalConfig) {
        return SyncEnvLog.builder()
                .key(IdWorker.getIdStr())
                .globalConfig(globalConfig)
                .modelId(globalConfig.getModel().getId())
                .dataSourceId(globalConfig.getDataSource().getId())
                .syncStartTime(LocalDateTime.now())
                .syncStatus(SyncStatus.SYNC_DOING)
                .syncEnv(globalConfig.getSyncToEnv())
                .syncExecBy(globalConfig.getSyncExecBy())
                .syncDdl(new ArrayList<>()).syncLog(new ArrayList<>()).syncPtsql(new ArrayList<>())
                .syncSandboxMock(globalConfig.isSyncSandboxMock())
                .build();
    }

    public static String generateKey(String modelId, String tableId) {
        BmAssetUtils.notNulls(new String[]{modelId, tableId}, "模型、表id不可为空");
        return String.join("-", modelId, tableId);
    }

    public LocalDateTime getSyncEndTime() {
        return syncEndTime == null ? LocalDateTime.now() : syncEndTime;
    }

    public LocalDateTime getSyncStartTime() {
        return syncStartTime == null ? LocalDateTime.now() : syncStartTime;
    }

    /**
     * 获取执行人邮件
     *
     * @return
     */
    public String getSyncExecByEmail() {
        return DapConstant.formatEmail(this.syncExecBy, true);
    }

    /**
     * 获取最新行同步时间
     *
     * @return time
     */
    public LocalDateTime getSyncTime() {
        return this.syncEndTime == null ? this.syncStartTime : syncEndTime;
    }

    public String getSyncScriptStr() {
        return JSON.toJSONString(this.syncScript);
    }

    public String getSyncLogStr(String char0) {
        if (char0 == null) {
            char0 = "\n";
        }
        return String.join(char0, syncLog);
    }

    /**
     * 生成对应的日志路径
     * <p>
     * 生成路径
     */
    public String genSyncLogPath() {
        if (basePath == null) {
            basePath = LOG_BASE_PATH;
        }
        if (Files.notExists(Paths.get(basePath))) {
            try {
                Files.createDirectories(Paths.get(basePath));
            } catch (IOException e) {
                throw new DapThrowException("初始化日志基础目录失败", e);
            }
        }
        this.syncLogPath = basePath + generateKey() + "-" + getKey() + ".log";
        return this.syncLogPath;
    }

    public String getSyncLogPath() {
        return genSyncLogPath();
    }

    public String generateKey() {
        return generateKey(modelId, tableId);
    }

}
